// -*- C++ -*-
//
//  This file is part of Siena, a wide-area event notification system.
//  See http://www.inf.usi.ch/carzaniga/siena/
//
//  Authors: Antonio Carzaniga
//  See the file AUTHORS for full details. 
//
//  Copyright (C) 2003 University of Colorado
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 2
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
//  USA, or send email to one of the authors.
//
//
// $Id: bloom_set.h,v 1.9 2010-03-11 15:16:39 carzanig Exp $
//
#ifndef BLOOM_SET_H
#define BLOOM_SET_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef USE_STD_BITSET
#include <bitset>
#endif

#include "hash.h"

namespace siena {

#ifdef USE_STD_BITSET

template<unsigned int size>
class bloom_set_t {
private:
    std::bitset<size> bv;

public:
    bloom_set_t() throw () : bv() { }

    void add_string(const char * begin, const char * end) throw () {
	bv.set(hash_string(begin, end) % size);
    }

    bool covers(const bloom_set_t & s) throw () {
	return (bv & s.bv) == s.bv;
    }
};

typedef bloom_set_t<64> bloom_set;

#else /* do not use <bitset> */

class bloom_set {
private:
    typedef unsigned long long bitvector_t;
    static const unsigned int size = sizeof(bitvector_t) * 8;

    bitvector_t bv;

public:
    bloom_set() throw () : bv(0) { }

    void add_string(const char * begin, const char * end) throw () {
        bitvector_t m = 1;
        //
        // this works because (i.e., only if!) size is a power of 2
        m <<= (hash_string(begin, end) & (size - 1));
        bv |= m;
    }

    bool covers(const bloom_set & s) throw () {
        return (bv & s.bv) == s.bv;
    }
};

#endif

} // end namespace siena

#endif
